package com.istock.union.user.utils;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

/**
 * web中比较常见的公共方法
 * @author senvon
 *
 */
public abstract class WebCommonUtils {

	public static String findRemoteAddr(HttpServletRequest request) {
		if(request == null) {
			return null;
		}
		String ip = request.getHeader("x-forwarded-for");
		if(StringUtils.isBlank(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if(StringUtils.isBlank(ip)) {
			ip = request.getHeader("X-Forwarded-For");
		}
		if(StringUtils.isBlank(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if(StringUtils.isBlank(ip)) {
			ip = request.getHeader("X-Real-IP");
		}
		if(StringUtils.isBlank(ip)) {
			ip = request.getRemoteAddr();
		}
		if(ip.equalsIgnoreCase("0:0:0:0:0:0:0:1")) {
			ip = "127.0.0.1";
		}
		return ip;
	}
	
	/**判断当前请求是否为一个ajax请求
	 * @param request
	 * @return
	 */
	public static boolean isAjax(HttpServletRequest request){
		return (request.getHeader("X-Requested-With") != null  && "XMLHttpRequest".equals( request.getHeader("X-Requested-With"))) ;
	}
	
	/**在验证登录标识失败以后,跳转url,需要生成fromurl,方便在登录完成以后,对url进行
	 * 在loginUrl后面,拼接上fromurl
	 * fromurl 因为需要传递在参数上,对fromurl进行unionCode编码
	 * 
	 * 这边的获取方式主要有2种
	 * 1.从request中的referer里面获取---这种获取的劣势在于,如果上一个页面打开的地址是由post提交刷新的页面,那么这边获取到的是post的url
	 * 		,fromurl将会以重定向的方式跳转,post的参数无法携带
	 * 2.自己记录所有有效页面的url,从缓存中获取
	 * 
	 * @param request 
	 * @param loginUrl
	 * @return
	 */
	public static String generateRediectUrl(HttpServletRequest request , String loginUrl){
		String lastGetUrl = request.getHeader("Referer");
		return generateFromUrl(loginUrl , "fromUrl" , lastGetUrl);
	}
	
	/**在原本的url后面,带上fromUrl参数
	 * target?/&fromUrlName=fromUrl
	 * @param targetUrl
	 * @param fromUrlName
	 * @param fromUrl
	 * @return
	 */
	public static String generateFromUrl(String targetUrl ,String fromUrlName, String fromUrl){
		StringBuffer sb = new StringBuffer();
		if(StringUtils.isNotBlank(targetUrl)){
			sb.append(targetUrl);
		}
		if(StringUtils.isNotBlank(fromUrl)){
			
			if(sb.indexOf("?")>0){
				if(sb.indexOf("?") != sb.length()-1){
					sb.append("&");
				}
			}else{
				sb.append("?");
			}
			
			sb.append(fromUrlName + "=");
			
			Map<String , Object> urlParameter = findUrlParameter(fromUrl);
			
			if(urlParameter != null && !urlParameter.isEmpty()){
				List<String> paramList = new ArrayList<String>();
				for(Entry<String , Object> paramter : urlParameter.entrySet()){
					String p = paramter.getKey();
					if(paramter.getValue() != null){
						p += "=" + paramter.getValue();
					}
					paramList.add(p);
				}
				if(paramList != null && paramList.size()>0){
					String parameterStr = StringUtils.join(paramList.toArray(), "&");
					StringBuffer targetFromUrl = new StringBuffer(fromUrl.indexOf("?")>0?fromUrl.substring(0, fromUrl.indexOf("?")):fromUrl);
					targetFromUrl.append("?").append(parameterStr);
					
					sb.append(URLEncoder.encode(targetFromUrl.toString()));
				}
			}else{
				sb.append(URLEncoder.encode(fromUrl));
			}
		}
		return sb.toString();
	}
	
	/**获得一个url里面的参数
	 * @param url
	 * @return
	 */
	public static Map<String , Object> findUrlParameter(String url){
		
		Map<String , Object> result = new HashMap<String , Object>();
		int parameterLocation = StringUtils.indexOf(url, "?");
		if(parameterLocation >0){
			String subString = StringUtils.substring(url, parameterLocation+1);
			if(StringUtils.isNotBlank(subString)){
				String[] keyPairArray = StringUtils.split(subString, "&");
				if(keyPairArray != null ){
					for(String keyPair : keyPairArray){
						String[] keyAndPair = StringUtils.split(keyPair, "=");
						if(keyAndPair != null && keyAndPair.length>0){
							String key = keyAndPair[0];
							String value = null;
							if(keyAndPair.length>1){
								value = keyAndPair[1];
							}
							result.put(key, value);
						}
					}
				}
			}
		}
		return result;
	}
	
	/**从fromUrl中获得访问的domain
	 * @param fromUrl 请求url
	 * @return
	 */
	public static String findDomain(String fromUrl) {
		String regx = "https?://((\\w+(\\.)?)+(:\\d+)*)(/.*)*";
		
		Pattern p = Pattern.compile(regx);
		Matcher m = p.matcher(fromUrl);
		if(m.matches()) {
			return m.group(1);
		}
		return null;
		
	}
	
	/**对一个response写入cookie
	 * @param response
	 * @param name
	 * @param value
	 * @param domain
	 * @param maxAge
	 */
	public static void addCookie(HttpServletResponse response,String name,String value,String domain,int maxAge , String path){
	    Cookie cookie = new Cookie(name,value);
	    cookie.setPath(StringUtils.isNotBlank(path)?path:"/");
	    if(StringUtils.isNotBlank(domain)){
	    	cookie.setDomain(domain);
	    }
	    cookie.setMaxAge(maxAge);
	    cookie.setHttpOnly(true);
//	    cookie.setSecure(true);
	    response.addCookie(cookie);
	}
	
	/**删除一个cookie
	 * @param response
	 * @param name
	 */
	public static void removeCookie(HttpServletResponse response , String name){
		Cookie cookie = new Cookie(name, null);
		cookie.setMaxAge(0);
		cookie.setPath("/");
		response.addCookie(cookie);
	}
	
	/**从当前的请求中,获取登录标识
	 * 可以不确定登录标识从哪边获取,但是需要明确获取顺序
	 * 1.从parameter中获得
	 * 2.从请求header里面获取
	 * 3.从cookie中获取
	 * 
	 * 如果请求里面不包含登录标识,则返回null
	 * @param request
	 * @param tokenName 
	 * @return
	 */
	public static String findToken(HttpServletRequest request , String tokenName){
		String token = request.getParameter(tokenName);
		if(StringUtils.isEmpty(token)){
			token = request.getHeader(tokenName);
		}
		if(StringUtils.isEmpty(token)){
			Cookie[] cookies = request.getCookies();
			if(cookies != null){
				for(Cookie cookie : cookies){
					if(cookie.getName().equalsIgnoreCase(tokenName)){
						token = cookie.getValue();
						break;
					}
				}
			}
		}
		return token;
	}
	
	/**从当前请求中,获取登录的ticket
	 * 可以不确定登录标识从哪边获取,但是需要明确获取顺序
	 * 1.从parameter中获得
	 * 2.从请求header里面获取
	 * 
	 * ticket不能从cookie中获取
	 * 
	 * 如果请求里面不包含登录标识,则返回null
	 * @param request
	 * @return
	 */
	public static String findTicket(HttpServletRequest request , String ticketName){
		String token = request.getParameter(ticketName);
		if(StringUtils.isEmpty(token)){
			token = request.getHeader(ticketName);
		}
		return token;
	}
	
	/**从requestURI中除去contextPath
	 * 方便权限校验和判断
	 * @param request
	 * @return
	 */
	public static String findAccessPath(HttpServletRequest request){
		String url = request.getRequestURI();
		String contextPath = request.getContextPath();
		
		return url.substring(contextPath.length());
	}
	
	/**合并2个url,处理中间是否需要加"/"
	 * @param url
	 * @param url2
	 * @return
	 */
	public static String contactPath(String url , String url2) {
		StringBuffer sb = new StringBuffer(url);
		if(url.endsWith("/")) {
			//前面的url是以/结尾
			if(url2.startsWith("/")) {
				sb.append(url2.substring(1));
			}else {
				sb.append(url2);
			}
		}else {
			//前面的url没有以/结尾
			if(!url2.startsWith("/")) {
				sb.append("/");
			}
			sb.append(url2);
		}
		return sb.toString();
	}
	
	/**跳转页面的targetUrl的生成
	 * 统一逻辑
	 * @param baseUrl 配置中的baseUrl 
	 * @param contextPath 当前部署的contextPath
	 * @param targetUrl 目标跳转的url
	 * @return
	 */
	public static String generateTargetUrl(String contextPath , String targetUrl) {
		if(targetUrl.toLowerCase().startsWith("http") || targetUrl.startsWith("/")) {
			return targetUrl;
		}
		return contactPath(contextPath , targetUrl);
	}
	
	public static String findUrlPrefix(String url) {
		int i = StringUtils.lastIndexOf(url, ".");
		if(i >0) {
			return url.substring(i);
		}
		return null;
	}
}
